package com.example.springboot.system.controller;

import com.alibaba.excel.EasyExcel;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.springboot.common.annotate.JwtToken;
import com.example.springboot.common.resp.Result;
import com.example.springboot.common.utils.JWTUtils;
import com.example.springboot.system.entity.BooknoEntity;
import com.example.springboot.system.entity.BooksEntity;
import com.example.springboot.system.entity.SortsEntity;
import com.example.springboot.system.mapper.BooksMapper;
import com.example.springboot.system.service.BooknoService;
import com.example.springboot.system.service.BooksService;
import com.example.springboot.system.service.SortsService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.Data;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 图书总表 前端控制器
 * </p>
 *
 * @author he
 * @since 2024-05-28
 */

@Tag(name = "书册管理")
@RestController
@RequestMapping("/booksEntity")
public class BooksController {

    @Data
    static class Books {
        private Integer id;
        private String code;
        private String isbn;
        private String name;
        private Integer sortsId;
        private String sortsName;
        private String author;
        private String publish;
        private BigDecimal price;
        private Integer volume;
        private Integer inventory;
        private String createBy;
        private String createTime;
        private String updateBy;
        private String updateTime;
        private Integer undock;
        private Integer unlucky;
        private String remark;
    }

    @Autowired
    private BooksMapper booksMapper;

    @Autowired
    private BooksService booksService;

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    @Autowired
    private SortsService sortsService;

    @JwtToken
    @Operation(summary = "列表")
    @PostMapping("/listBooks")
    public Result<?> listBooks() {
        QueryWrapper<BooksEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("undock", 1);
        return Result.success("数据请求成功", booksService.list(wrapper));
    }

    @JwtToken
    @Operation(summary = "列表分页")
    @PostMapping("/listPageBooks")
    public Result<?> listPageBooks(@RequestParam Integer page, @RequestParam Integer pageSize) {
        //分页参数
        Page<BooksEntity> rowPage = new Page(page, pageSize);
        QueryWrapper<BooksEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("undock", 1);
        rowPage = booksMapper.selectPage(rowPage, wrapper);
        Page<Books> rowPageBooks = new Page(page, pageSize);
        BeanUtils.copyProperties(rowPage,rowPageBooks);
        //
        ArrayList<Books> list = new ArrayList<>();
        List<BooksEntity> records = rowPage.getRecords();
        for (int i = 0; i < records.size(); i++) {
            BooksEntity booksEntity = records.get(i);
            Books books = new Books();
            BeanUtils.copyProperties(booksEntity, books);
            Integer sortsId = booksEntity.getSortsId();
            SortsEntity sorts = sortsService.getById(sortsId);
            books.setSortsName(sorts.getName());
            list.add(books);
        }
        rowPageBooks.setRecords(list);
        return Result.success("数据请求成功", rowPageBooks);
    }

    @JwtToken
    @Operation(summary = "查询编号")
    @PostMapping("/findByIDBooks/{param}")
    public Result<?> findByIDBooks(@PathVariable @Validated String param) {
        QueryWrapper<BooksEntity> wrapper = new QueryWrapper<>();
        wrapper.like(("books_id"), param);
        wrapper.eq(("undock"), 1);
        if (booksService.count(wrapper) == 0) return Result.success("查询成功，但符合条件数据为空");
        return Result.success("查询成功", booksMapper.selectList(wrapper));
    }

    @JwtToken
    @Operation(summary = "查询名称")
    @PostMapping("/findByNameBooks/{param}")
    public Result<?> findByNameBooks(@PathVariable @Validated String param) {
        QueryWrapper<BooksEntity> wrapper = new QueryWrapper<>();
        wrapper.like(("books_name"), param);
        wrapper.eq(("undock"), 1);
        if (booksService.count(wrapper) == 0) return Result.failure("查询成功，但符合条件数据为空");
        return Result.success("查询成功", booksMapper.selectList(wrapper));
    }

    @Operation(summary = "条件查询")
    @PostMapping("/findBooks")
    public Result<?> findBooks(@RequestBody BooksEntity entity) {
        QueryWrapper<BooksEntity> wrapper = new QueryWrapper<>();
        if (entity.getName() != "") wrapper.like(("books_name"), entity.getName());
        if (entity.getCode() != "") wrapper.like(("books_code"), entity.getCode());
        if (entity.getAuthor() != "") wrapper.like(("books_author"), entity.getAuthor());
        if (entity.getPublish() != "") wrapper.like(("books_publish"), entity.getPublish());
        if (entity.getSortsId() != 0) wrapper.like(("books_sorts_id"), entity.getSortsId());
        wrapper.like(("unlucky"), entity.getUnlucky());
        wrapper.eq(("undock"), 1);
        if (booksService.count(wrapper) == 0) return Result.failure("查询成功，但符合条件数据为空");
        List<BooksEntity> list = booksMapper.selectList(wrapper);
        ArrayList<Books> arrayList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            BooksEntity booksEntity = list.get(i);
            Books books = new Books();
            BeanUtils.copyProperties(booksEntity, books);
            SortsEntity sorts = sortsService.getById(books.getSortsId());
            books.setSortsName(sorts.getName());
            arrayList.add(books);
        }
        return Result.success("查询成功", arrayList);
    }

    @Autowired
    private BooknoService booknoService;

    @JwtToken
    @Operation(summary = "保存数据")
    @PostMapping("/insert")
    public Result<?> insertBooks(@RequestBody @Validated BooksEntity entity, HttpServletRequest httpServletRequest) {
        String token = httpServletRequest.getHeader("token");
        DecodedJWT decodedJWT = JWTUtils.resolveToken(token);
        //保存
        QueryWrapper<BooksEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(("books_id"), entity.getId());
        if (booksService.count(wrapper) != 0) return Result.failure("保存失败，编号已存在");
        //设置创建者
        String name = decodedJWT.getClaim("name").asString();
        entity.setCreateBy(name);
        entity.setCreateTime(sdf.format(new Date()));
        //添加书册
        boolean save = booksService.save(entity);
        if (!save) return Result.failure("书册保存失败，保存失败");
        //添加书本
        insertBookno(entity, httpServletRequest);
        return Result.success("保存成功");
    }

    @JwtToken
    @Operation(summary = "永久删除")
    @PostMapping("/delete/{param}")
    public Result<?> deleteBooks(@PathVariable @Validated String param) {
        //删除书本
        QueryWrapper<BooknoEntity> wrapperB = new QueryWrapper<>();
        wrapperB.eq("bookno_books_id", param);
        booknoService.remove(wrapperB);
        //删除书册
        QueryWrapper<BooksEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(("books_id"), param);
        if (booksService.remove(wrapper)) return Result.success("删除成功");
        return Result.failure("系统超时，删除失败");
    }

    @JwtToken
    @Operation(summary = "暂时删除")
    @PostMapping("/deleteTemp/{param}")
    public Result<?> deleteTempBooks(@PathVariable @Validated String param, HttpServletRequest httpServletRequest) {
        String token = httpServletRequest.getHeader("token");
        DecodedJWT decodedJWT = JWTUtils.resolveToken(token);
        //修改
        QueryWrapper<BooksEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(("books_id"), param);
        if (booksService.count(wrapper) == 0) return Result.failure("删除失败，编号不存在");
        BooksEntity books = booksService.getOne(wrapper);
        books.setUndock(0);
        //设置修改者
        String name = decodedJWT.getClaim("name").asString();
        books.setUpdateBy(name);
        books.setUpdateTime(sdf.format(new Date()));
        if (booksService.updateById(books)) return Result.success("删除成功");
        return Result.failure("系统超时，删除失败");
    }

    @JwtToken
    @Operation(summary = "恢复列表")
    @PostMapping("/recoverList")
    public Result<?> recoverListBooks() {
        QueryWrapper<BooksEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("undock", 0);
        return Result.success(booksMapper.selectList(wrapper));
    }

    @JwtToken
    @Operation(summary = "恢复数据")
    @PostMapping("/recover/{param}")
    public Result<?> recoverBooks(@PathVariable @Validated String param, HttpServletRequest httpServletRequest) {
        String token = httpServletRequest.getHeader("token");
        DecodedJWT decodedJWT = JWTUtils.resolveToken(token);
        //修改
        QueryWrapper<BooksEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(("books_id"), param);
        if (booksService.count(wrapper) == 0) return Result.failure("恢复失败，编号不存在");
        BooksEntity books = booksService.getOne(wrapper);
        books.setUndock(1);
        //设置修改者
        String name = decodedJWT.getClaim("name").asString();
        books.setUpdateBy(name);
        books.setUpdateTime(sdf.format(new Date()));
        if (booksService.updateById(books)) return Result.success("数据恢复成功");
        return Result.failure("系统超时，数据恢复失败");
    }

    @JwtToken
    @Operation(summary = "修改编号")
    @PostMapping("/update")
    public Result<?> updateBooks(@RequestBody @Validated BooksEntity entity, HttpServletRequest httpServletRequest) {
        //获取token
        String token = httpServletRequest.getHeader("token");
        DecodedJWT decodedJWT = JWTUtils.resolveToken(token);
        //修改
        QueryWrapper<BooksEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(("books_id"), entity.getId());
        if (booksService.count(wrapper) == 0) return Result.failure("修改失败，编号不存在");
        //设置修改者
        String name = decodedJWT.getClaim("name").asString();
        entity.setUpdateBy(name);
        entity.setUpdateTime(sdf.format(new Date()));
        if (booksService.updateById(entity)) return Result.success("修改成功");
        return Result.failure("系统超时，修改失败");
    }

    @Operation(summary = "导出数据")
    @PostMapping("exportExcel")
    public void exportExcelBooks(HttpServletResponse response) throws IOException {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        String fileName = URLEncoder.encode("Excel数据表", StandardCharsets.UTF_8).replaceAll("\\+", "%20");
        List<BooksEntity> list = booksService.list();
        response.setHeader("Content-disposition", "attachment;filename*=" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), BooksEntity.class).sheet("Excel数据表").doWrite(list);
    }

    @JwtToken
    @Operation(summary = "导入数据")
    @PostMapping("/importExcel")
    public Result<?> importExcelBooks(MultipartFile file, HttpServletRequest httpServletRequest) {
        try {
            //获取文件的输入流
            InputStream inputStream = file.getInputStream();
            List<BooksEntity> list = EasyExcel.read(inputStream) //调用read方法
                    //注册自定义监听器，字段校验可以在监听器内实现
                    //.registerReadListener(new BooksListener())
                    .head(BooksEntity.class) //对应导入的实体类
                    .sheet(0) //导入数据的sheet页编号，0代表第一个sheet页，如果不填，则会导入所有sheet页的数据
                    .headRowNumber(1) //列表头行数，1代表列表头有1行，第二行开始为数据行
                    .doReadSync();//开始读Excel，返回一个List<T>集合，继续后续入库操作
            //模拟导入数据库操作
            String token = httpServletRequest.getHeader("token");
            DecodedJWT decodedJWT = JWTUtils.resolveToken(token);
            String id = decodedJWT.getClaim("id").asString();
            String acc = decodedJWT.getClaim("acc").asString();
            String name = decodedJWT.getClaim("name").asString();
            for (BooksEntity entity : list) {
                QueryWrapper<BooksEntity> wrapper = new QueryWrapper<>();
                wrapper.eq("books_id", entity.getId());
                long count = booksService.count(wrapper);
                if (count == 0) {
                    booksService.save(entity);
                    insertBookno(entity, httpServletRequest);
                }
                if (count == 1) {
                    booksService.updateById(entity);
                    QueryWrapper<BooknoEntity> wrapperBNO = new QueryWrapper<>();
                    wrapperBNO.eq("bookno_books_id", entity.getId());
                    booknoService.remove(wrapperBNO);
                    insertBookno(entity, httpServletRequest);
                }
            }
            return Result.success("导入成功");
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }

    public void insertBookno(BooksEntity entity, HttpServletRequest httpServletRequest) {
        String token = httpServletRequest.getHeader("token");
        DecodedJWT decodedJWT = JWTUtils.resolveToken(token);
        String id = decodedJWT.getClaim("id").asString();
        String acc = decodedJWT.getClaim("acc").asString();
        String name = decodedJWT.getClaim("name").asString();
        for (int i = 0; i < entity.getVolume(); i++) {
            SortsEntity sorts = sortsService.getById(entity.getSortsId());
            BooknoEntity bookno = new BooknoEntity();
            bookno.setBooksId(entity.getId());
            String booknoCode = sorts.getCode() + "-" + entity.getCode() + "-" + i;
            bookno.setCode(booknoCode);
            bookno.setName(entity.getName());
            bookno.setCreateBy(name);
            bookno.setCreateTime(sdf.format(new Date()));
            booknoService.save(bookno);
        }
    }

}
